home *** CD-ROM | disk | FTP | other *** search
- #include "string.h"
- #include "AppInterface.h"
-
- #include "CMApplication.h"
- #include "ColorPicker.h"
-
- ////////////////////////////////////////////////////////
- // Defines
-
- // Edit menu constants redefined for the article code
- #define kMyEditMenuID kEditMenuID
- #define kMyUndoItem iUndo
- #define kMyCutItem iCut
- #define kMyCopyItem iCopy
- #define kMyPasteItem iPaste
- #define kMyClearItem iClear
-
- // ID of App dialog for a picker
- #define kMyDialogID 129
-
- // App dialog items
- #define kRevertButton 1
- #define kEditItem 2
- #define kStatText 3
- #define kMyLastItem kStatText
-
-
- /////////////////////////////////////
- // Globals
-
- RGBColor myRGBColor = {65535, 32767, 0}; // A nice pukey orange.
- picker myPicker = nil; // Global picker reference.
- DialogPtr myDialog = nil;
- WindowPtr myDocWindow = nil;
- extern MenuHandle gPickerMenuHandle;
-
-
- //////////////////////////////////
- // Prototypes
-
- pascal Boolean MyEventProc(EventRecord *event);
- pascal void MyColorChangedProc(long userData, PMColorPtr newColor);
- pascal void MyModelessColorChangedProc(long userData, PMColorPtr newColor);
- void PickAColor(void);
- void DoNewColorStuff(PMColor *theColor);
- void DoTheUpdate(WindowPtr aWindow);
- OSErr BuildModelessSysDialog(void);
- OSErr BuildPickerDialog(void);
- OSErr BuildAppDialog(void);
- Boolean SampleDoEvent(EventRecord *event);
- void UseNewColor(picker thePicker);
- void UseOriginalColor(picker thePicker);
- void HandleAppItem(short itemHit);
- Boolean DoMenu(EventRecord *event);
- void HandleMenuChoice(long mChoice);
- void CloseAppPicker(void);
-
- // Event-filter procedure and color-changed procedure
-
- pascal Boolean MyEventProc(EventRecord *event) {
- Boolean handled = false; // Assume we don't handle the event.
-
- switch(event->what) {
- case updateEvt:
- // Check to see if the update is for our window.
- if((WindowPtr) event->message == myDocWindow) {
- DoTheUpdate(myDocWindow);
- handled = true;
- }
- }
- return handled;
- }
-
- pascal void MyColorChangedProc(long userData, PMColorPtr newColor) {
- GrafPtr port;
- CWorld cWorld;
- CMColor color;
- CMError cwError;
-
- GetPort(&port);
- SetPort(myDocWindow);
-
- // If the color has a profile, convert it to RGB space.
- if(newColor->profile) {
- // Create a color world and convert the color. This color world
- // matches from the color's space to the system space (RGB).
- cwError = CWNewColorWorld(&cWorld, newColor->profile, 0L);
- if(cwError == noErr || cwError == CMProfilesIdentical) {
- // We created the color world. Now match the color using a copy
- // so that we don't munge the original.
- color = newColor->color;
- CWMatchColors(cWorld, &color, 1);
- CWDisposeColorWorld(cWorld);
- }
- } else
- color.rgb = newColor->color.rgb;
-
- // Set our global color storage and paint the port with the new color.
- myRGBColor = color.rgb;
- RGBForeColor(&color.rgb);
- PaintRect(&myDocWindow->portRect);
-
- SetPort(port);
- }
-
- void PickAColor(void)
- {
- // Calling PickColor
-
- ColorPickerInfo cpInfo;
- PMColor savedColor;
-
- // Set the input color to be an RGB color in system space.
- cpInfo.theColor.color.rgb = myRGBColor;
- cpInfo.theColor.profile = 0L;
-
- // We're not picking for a destination profile.
- cpInfo.dstProfile = 0L;
-
- cpInfo.flags = AppIsColorSyncAware | CanModifyPalette | CanAnimatePalette;
-
- // Center the picker on the deepest color screen (we don't need to worry
- // about the dialogOrigin field in this case).
- cpInfo.placeWhere = kDeepestColorScreen;
-
- // Use the default picker.
- cpInfo.pickerType = 0L;
-
- // Install the callbacks.
- cpInfo.eventProc = MyEventProc;
- cpInfo.colorProc = MyColorChangedProc;
- cpInfo.colorProcData = 0L;
-
- strcpy((char *)cpInfo.prompt,(char *)"\pChoose a new color");
-
- // Tell the Color Picker Manager about the Edit menu.
- cpInfo.mInfo.editMenuID = kMyEditMenuID;
- cpInfo.mInfo.cutItem = kMyCutItem;
- cpInfo.mInfo.copyItem = kMyCopyItem;
- cpInfo.mInfo.pasteItem = kMyPasteItem;
- cpInfo.mInfo.clearItem = kMyClearItem;
- cpInfo.mInfo.undoItem = kMyUndoItem;
-
- // Save the current color, in case the user cancels
- savedColor = cpInfo.theColor;
-
- // And finally, pick that color!
- if(PickColor(&cpInfo) == noErr && cpInfo.newColorChosen)
- // Go use this new color. Remember it can be in any color space.
- DoNewColorStuff(&cpInfo.theColor);
- else
- // Canceled or an error, restore old color
- DoNewColorStuff(&savedColor);
- }
-
- void DoNewColorStuff(PMColor *theColor)
- {
- if(theColor->profile)
- SysBeep(10); // exercise for the reader <snicker>
- else
- {
- SetPort(myDocWindow);
- myRGBColor = theColor->color.rgb;
- RGBForeColor(&myRGBColor);
- PaintRect(&myDocWindow->portRect);
- }
- }
-
- void DoTheUpdate(WindowPtr aWindow)
- {
- BeginUpdate(aWindow);
- SetPort(aWindow);
- RGBForeColor(&myRGBColor);
- PaintRect(&aWindow->portRect);
- EndUpdate(aWindow);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
-
- OSErr BuildModelessSysDialog(void)
- {
- // A modeless system-owned color picker dialog
-
- SystemDialogInfo sInfo;
- OSErr result;
-
- sInfo.flags = DialogIsMoveable + AppIsColorSyncAware + CanModifyPalette
- + CanAnimatePalette;
- sInfo.pickerType = 0L;
- sInfo.placeWhere = kDeepestColorScreen;
- sInfo.mInfo.editMenuID = kMyEditMenuID;
- sInfo.mInfo.cutItem = kMyCutItem;
- sInfo.mInfo.copyItem = kMyCopyItem;
- sInfo.mInfo.pasteItem = kMyPasteItem;
- sInfo.mInfo.clearItem = kMyClearItem;
- sInfo.mInfo.undoItem = kMyUndoItem;
-
- myPicker = nil; // not in listing!
-
- result = CreateColorDialog(&sInfo, &myPicker);
- return result;
- }
-
- OSErr BuildAppDialog(void)
- {
- ApplicationDialogInfo aInfo;
- OSErr result;
-
- // First create the dialog (make sure it's a color dialog so the color
- // picker can do all the color stuff it needs to do!).
- myDialog = GetNewDialog(kMyDialogID, nil, (WindowPtr)-1);
-
- // Set up the ApplicationDialogInfo structure
- aInfo.flags = DialogIsMoveable + AppIsColorSyncAware +
- CanModifyPalette + CanAnimatePalette;
- aInfo.pickerType = 0L;
- aInfo.theDialog = myDialog;
-
- // Put the color picker's origin at (0,0) in the dialog.
- aInfo.pickerOrigin.h = 0;
- aInfo.pickerOrigin.v = 0;
-
- // Set up edit menu info
- aInfo.mInfo.editMenuID = kMyEditMenuID;
- aInfo.mInfo.cutItem = kMyCutItem;
- aInfo.mInfo.copyItem = kMyCopyItem;
- aInfo.mInfo.pasteItem = kMyPasteItem;
- aInfo.mInfo.clearItem = kMyClearItem;
- aInfo.mInfo.undoItem = kMyUndoItem;
-
- // Finally, add the color picker to it.
- result = AddPickerToDialog(&aInfo, &myPicker);
- return result;
- }
-
- OSErr BuildPickerDialog(void)
- {
- PickerDialogInfo pInfo;
- OSErr result;
-
- pInfo.flags = DialogIsMoveable + AppIsColorSyncAware + CanModifyPalette
- + CanAnimatePalette;
- pInfo.pickerType = 0L;
- pInfo.mInfo.editMenuID = kMyEditMenuID;
- pInfo.mInfo.cutItem = kMyCutItem;
- pInfo.mInfo.copyItem = kMyCopyItem;
- pInfo.mInfo.pasteItem = kMyPasteItem;
- pInfo.mInfo.clearItem = kMyClearItem;
- pInfo.mInfo.undoItem = kMyUndoItem;
-
- result = CreatePickerDialog(&pInfo, &myPicker);
- return result;
- }
-
- pascal void MyModelessColorChangedProc(long userData, PMColorPtr newColor) {
- GrafPtr port;
- CWorld cWorld;
- CMColor color;
- CMError cwError;
-
- GetPort(&port);
- SetPort(myDocWindow);
-
- // Now check to see if the color has a profile. If so, we need to
- // convert it to RGB space.
- if(newColor->profile) {
- // Create a color world and convert the color. This color world
- // matches from the color's space to the system space (RGB).
- cwError = CWNewColorWorld(&cWorld, newColor->profile, 0L);
- if(cwError == noErr || cwError == CMProfilesIdentical) {
- // We created the color world. Now match the color using a copy
- // so that we don't munge the original.
- color = newColor->color;
- CWMatchColors(cWorld, &color, 1);
- CWDisposeColorWorld(cWorld);
- }
- } else
- color.rgb = newColor->color.rgb;
-
- // Just paint the port with the new color.
- RGBForeColor(&color.rgb);
- PaintRect(&myDocWindow->portRect);
-
- SetPort(port);
- }
-
- ///////////////////////////////////////////////////////////////////
-
- // Sample event loop
-
- #define IsMenuKey(x) ((x)->what == keyDown && (x)->modifiers & cmdKey)
-
- Boolean SampleDoEvent(EventRecord *event) {
- Boolean handled = false, isMenuEvent = false;
- EventData pEvent;
- short inWhere;
- WindowPtr whichWindow;
-
- // We are assuming that the application always wants to handle menus.
- if(event->what == mouseDown) {
- inWhere = FindWindow(event->where, &whichWindow);
- if(inWhere == inMenuBar)
- isMenuEvent = true;
- }
- if(isMenuEvent || IsMenuKey(event)) {
- DoMenu(event);
- handled = true;
- }
-
- // If the event's not handled yet, call the Color Picker Manager to
- // give it a shot.
- if(!handled && myPicker != nil) {
- pEvent.event = event;
- pEvent.colorProc = MyModelessColorChangedProc;
- pEvent.colorProcData = 0L;
- DoPickerEvent(myPicker, &pEvent);
- handled = pEvent.handled;
-
- // If the color picker handled it, we might want to do something
- // with the results.
- if(handled)
- {
- switch(pEvent.action) {
- case kDidNothing:
- break;
- case kColorChanged:
- UseNewColor(myPicker);
- break;
- case kOkHit:
- UseNewColor(myPicker);
- DisposeColorPicker(myPicker);
- myPicker = nil;
- break;
- case kCancelHit:
- UseOriginalColor(myPicker);
- DisposeColorPicker(myPicker);
- myPicker = nil;
- break;
- case kNewPickerChosen:
- // You shouldn't care about this.
- break;
- case kApplItemHit:
- // Handle the item as you would for the Dialog Manager.
- HandleAppItem(pEvent.itemHit);
- break;
- }
- }
- }
- if(!handled) {
- // The event hasn't been handled. Treat it as you would any normal
- // Macintosh event (in this case we do nothing, and the calling
- // routine handles it). If you have other dialogs, you need to call
- // DialogSelect. Remember, if the event is a mouseDown, you
- // already called FindWindow!
- }
- return handled;
- }
-
- void UseNewColor(picker thePicker)
- {
- PMColor newColor;
-
- GetPickerColor(thePicker, kNewColor, &newColor);
- DoNewColorStuff(&newColor);
- }
-
- void UseOriginalColor(picker thePicker)
- {
- PMColor oldColor;
-
- GetPickerColor(thePicker, kOriginalColor, &oldColor);
- DoNewColorStuff(&oldColor);
- }
-
- void HandleAppItem(short itemHit)
- {
- PMColor oldColor;
-
- switch(itemHit)
- {
- case kRevertButton:
- GetPickerColor(myPicker, kOriginalColor, &oldColor);
- SetPickerColor(myPicker, kNewColor, &oldColor);
- DoNewColorStuff(&oldColor);
- break;
-
- default:
- break;
- }
- }
-
- // Handling the Edit Menu
- Boolean DoMenu(EventRecord *event)
- {
- long mChoice;
- EditData eData;
- EditOperation eOperation;
-
- // If picker is in front and current edit item is the picker's,
- // set up the Edit menu how the picker wants it
- if (FrontWindow() == myDialog &&
- ((DialogPeek)myDialog)->editField + 1 > kMyLastItem) {
- MenuState mState;
- MenuHandle theMenu;
-
- GetPickerEditMenuState(myPicker, &mState);
- theMenu = GetMenu(kMyEditMenuID);
- if (mState.cutEnabled)
- EnableItem(theMenu, kMyCutItem);
- else
- DisableItem(theMenu, kMyCutItem);
- if (mState.copyEnabled)
- EnableItem(theMenu, kMyCopyItem);
- else
- DisableItem(theMenu, kMyCopyItem);
- if (mState.pasteEnabled)
- EnableItem(theMenu, kMyPasteItem);
- else
- DisableItem(theMenu, kMyPasteItem);
- if( mState.clearEnabled)
- EnableItem(theMenu, kMyClearItem);
- else
- DisableItem(theMenu, kMyClearItem);
- if (mState.undoEnabled)
- {
- SetItem(theMenu, kMyUndoItem, mState.undoString);
- EnableItem(theMenu, kMyUndoItem);
- }
- else
- DisableItem(theMenu, kMyUndoItem);
- }
-
- // Give the event to the Menu Manager.
- if (event->what == mouseDown)
- mChoice = MenuSelect(event->where);
- else
- mChoice = MenuKey(event->message);
-
- // If not the edit menu, handle normally
- if(HiWord(mChoice) != kMyEditMenuID)
- {
- HandleMenuChoice(mChoice);
- return true;
- }
-
- switch (LoWord(mChoice)) {
- case kMyCutItem:
- eOperation = kCut;
- break;
- case kMyCopyItem:
- eOperation = kCopy;
- break;
- case kMyPasteItem:
- eOperation = kPaste;
- break;
- case kMyClearItem:
- eOperation = kClear;
- break;
- case kMyUndoItem:
- eOperation = kUndo;
- break;
- default:
- eOperation = -1;
- break;
- }
- if (eOperation >= 0) {
- eData.theEdit = eOperation;
- DoPickerEdit(myPicker, &eData);
-
- // We're going to ignore the results here, and just assume the
- // color changed
- UseNewColor(myPicker);
- }
- HiliteMenu(0);
- return true;
- }
-
- void HandleMenuChoice(long mChoice)
- {
- int DoMenus(long mstuff);
-
- // The menu choice isn't in the edit menu, let the shell handle it.
- DoMenus(mChoice);
- }
-
- void CloseAppPicker(void)
- {
-
- if(myPicker != nil)
- {
- DisposeColorPicker(myPicker);
- myPicker = nil;
- }
-
- if(myDialog != nil)
- {
- DisposeDialog(myDialog);
- myPicker = nil;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////
- //
- // Miscellaneous code
-
- void SetPickerToColor(RGBColor *rgb);
- void SetPickerToColor(RGBColor *rgb) {
- PMColor aColor;
-
- aColor.color.rgb = *rgb;
- aColor.profile = 0L;
- SetPickerColor(myPicker, kOriginalColor, &aColor);
- SetPickerColor(myPicker, kNewColor, &aColor);
- }
-
- void GetCurrentColor(RGBColor *rgb);
- void GetCurrentColor(RGBColor *rgb) {
- PMColor aColor;
-
- GetPickerColor(myPicker, kNewColor, &aColor);
- *rgb = aColor.color.rgb;
- }
-
- void HandleError(void);
- void HandleError(void)
- {
- SysBeep(0);
- }
-
- void SetDestinationProfile(CMProfileHandle profile);
- void SetDestinationProfile(CMProfileHandle profile) {
- if (SetPickerProfile(myPicker, profile) != noErr)
- HandleError();
- }
-
- void GetDestinationProfile(CMProfileHandle profile);
- void GetDestinationProfile(CMProfileHandle profile) {
- if (GetPickerProfile(myPicker, &profile) != noErr)
- HandleError();
- }
-
- #include "Balloons.h"
- void DoBalloonHelp(void);
- void DoBalloonHelp(void) {
- HelpItemInfo helpInfo;
- short itemNo;
- Point where;
- OSErr err;
-
- GetMouse(&where);
- itemNo = FindDItem(myDialog, where) + 1;
-
- // Go and get the color picker's help item.
- helpInfo.options = 0;
- helpInfo.tip.v = helpInfo.tip.h = 0;
- SetRect(&helpInfo.altRect,0,0,0,0);
- helpInfo.theProc = 0;
- helpInfo.variant = 0;
- helpInfo.helpMessage.hmmHelpType = 0;
- helpInfo.helpMessage.u.hmmPictHandle = 0L;
- err = ExtractPickerHelpItem(myPicker, itemNo, 0, &helpInfo);
-
- // Show the balloon if we found one.
- if (err == noErr) {
- // If altRect is empty, we need to use the item's rectangle.
- if (EmptyRect(&helpInfo.altRect)) {
- short iType;
- Handle iHandle;
-
- GetDItem(myDialog, itemNo, &iType, &iHandle, &helpInfo.altRect);
- }
-
- // Convert the tip to dialog coordinates.
- helpInfo.tip.h += helpInfo.altRect.left;
- helpInfo.tip.v += helpInfo.altRect.top;
-
- // Convert the tip and altRect to global coordinates.
- LocalToGlobal(&helpInfo.tip);
- LocalToGlobal((Point *) &helpInfo.altRect.top);
- LocalToGlobal((Point *) &helpInfo.altRect.bottom);
-
- // Finally, put the balloon up.
- HMShowBalloon(&helpInfo.helpMessage, helpInfo.tip,
- &helpInfo.altRect, 0L, helpInfo.theProc, helpInfo.variant,
- kHMRegularWindow);
- }
- }
-